/*
 *
 *  Copyright (C) 2009 GSyC/LibreSoft
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *
 *  Author : Roberto Calvo Palomino <rocapal@gsyc.es>
 *
 */

package com.LibreGeoSocial.App; 

import java.util.ArrayList;
import java.util.Collections;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;

import com.LibreGeoSocial.Api.GeoNode;
import com.LibreGeoSocial.Api.GeoNodePositionComparator;
import com.LibreGeoSocial.Api.LibreGeoSocial;
import com.LibreGeoSocial.Api.User;
import com.LibreGeoSocial.App.AR.ARView;
import com.LibreGeoSocial.App.Maps.ResourcesMap;
import com.LibreGeoSocial.App.Monitoring.MonitoringMap;
import com.LibreGeoSocial.App.Routes.LocationService;
import com.LibreGeoSocial.App.Utils.LocationUtils;

public class FriendList extends GenericList implements OnClickListener {

	
	FriendsAdapter mAdapter; 
	
	// Main menu
	private static final int MENU_PEOPLE = Menu.FIRST + 1;
	private static final int MENU_FRIENDS = Menu.FIRST + 2;
	private static final int MENU_MAP = Menu.FIRST + 3;
	
	// Context menu
	private static final int MENU_DELETE_FRIEND = Menu.FIRST + 1;
	private static final int MENU_MONITOR_FRIEND = Menu.FIRST + 2;
	
	// Dialog
	private static final int DIALOG_ADD_FRIEND = 0;
	private static final int DIALOG_REMOVE_FRIEND = 1;
	private static final int DIALOG_NO_FRIENDS = 2;
	private static final int DIALOG_NO_LOCATION = 3;
	private static final int DIALOG_FRIENDSHIP_INVITATIONS = 4;
	
	// Request
	private static final int REQUEST_FRIENDSHIP_LIST = 1;
	
	static private ArrayList<GeoNode> mList, mFriendShipList, mFriendsList;
	
	/* if friends = true  => Friend List 
	 * if friends = false => World People List
 	 */
	
	private boolean friends = true;
	private User  userDialog = null;
	
	private Button prevButton;
	private Button nextButton;
	
	private Integer currentPage = 1;
	
	public void onCreate(Bundle savedInstanceState) {
		
		super.onCreate(savedInstanceState);		  					
		
		mList = LibreGeoSocial.getInstance().getFriendsList(true,0.0,currentPage);  
		
  		// Adapter for ListView
        mAdapter = new FriendsAdapter(this);
        setListAdapter(mAdapter);
        
		updateResources();
		
        mFriendShipList = LibreGeoSocial.getInstance().getFrienshipInvitations();

        if ( mFriendShipList.size()!=0 )
        {
        	showDialog(DIALOG_FRIENDSHIP_INVITATIONS);
        }
        else if ( mList.size()==0 )
        {
    		showDialog(DIALOG_NO_FRIENDS);
        }
        
		// Buttons to navigate
		prevButton = (Button) this.findViewById(R.id.btPrev);
		prevButton.setOnClickListener(this);

		nextButton = (Button) this.findViewById(R.id.btNext);
		nextButton.setOnClickListener(this);
        
        registerForContextMenu(this.getListView());
                

	}
	
	private void updateResources()
	{
		if (friends)
		{
			mList = LibreGeoSocial.getInstance().getFriendsList(true,0.0,currentPage);  
		}
		else
		{
//			mFriendsList = (ArrayList<GeoNode>) mList.clone();
			mList = LibreGeoSocial.getInstance().getUserList(true,0.0,null,currentPage);
		}
		
		if (mList!=null)
		{
			GeoNodePositionComparator comparator = new GeoNodePositionComparator();
			Collections.sort(mList, comparator);
			mAdapter.notifyDataSetChanged();
		}
    	
	}
	
	public void onClick(View v) {

		if (prevButton.isPressed() && currentPage==1)
		{
			Toast.makeText(getBaseContext(),
						"First Page. No previous results!", 
						Toast.LENGTH_LONG).show();
		}
		else
		{
			if (prevButton.isPressed()) 
			{
				currentPage--;
				
			} else if (nextButton.isPressed()) 
			{
				currentPage++;
			}
	
			updateResources();
		}

	}
	
	@Override
	public void onCreateContextMenu(ContextMenu menu, View view,  ContextMenuInfo menuInfo)
	{ 

		if (friends)
		{
          menu.add (0, MENU_DELETE_FRIEND, 0, "Delete Friend");
          menu.add (0, MENU_MONITOR_FRIEND, 0,"Monitors your Friend");
		}
	}
	
	@Override
	public boolean onContextItemSelected(MenuItem item) 
	{
		
		super.onContextItemSelected(item);
		
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
		userDialog = (User) mList.get(info.position);
		//Log.e("FriendList", String.valueOf(info.position));

		
		switch (item.getItemId()) {
		
			case MENU_DELETE_FRIEND:
				
				showDialog(DIALOG_REMOVE_FRIEND);
				
				break;
				
			case MENU_MONITOR_FRIEND:
			
	    		if ( userDialog.getLatitude()==-1.0 && 
	       			 userDialog.getLongitude()==-1.0)
	       			
	       		{
	       			showDialog(DIALOG_NO_LOCATION);	       			
	       		}
	    		else
	    		{
					Intent i = new Intent(this,MonitoringMap.class);
					i.putExtra("userId", userDialog.getId() );
		        	startActivity(i); 
	    		}
				break;		
		}
		
		return true;
	}

	
	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	
        super.onCreateOptionsMenu(menu);
        menu.add(0, MENU_PEOPLE, 0, "Show All People")
        		.setIcon(R.drawable.mundo)
                .setAlphabeticShortcut('A');
                
        menu.add(0, MENU_FRIENDS, 0, "Show Friends")
				.setIcon(R.drawable.users_two_38)
		        .setAlphabeticShortcut('F');
        
        menu.add(0, MENU_MAP, 0, "Show on map")
				.setIcon(R.drawable.logo)
				.setAlphabeticShortcut('M');
		        
        return true;
    }
	
    @Override
    public boolean onOptionsItemSelected (MenuItem item) {
    	
    	switch (item.getItemId()) {
    	
    		case MENU_PEOPLE:
    			
    			currentPage=1;
    			friends = false;
    			
    			mFriendsList = new ArrayList<GeoNode>();
    			ArrayList<GeoNode> auxList;
    			int i = 1;
    			while(!(auxList = LibreGeoSocial.getInstance().getFriendsList(true,0.0,i)).isEmpty()){
    				mFriendsList.addAll(auxList);
    				i++;
    				Log.e("FRIENDLIST", Integer.toString(i));
    			}
    			updateResources();
    			break;
    			
    		case MENU_FRIENDS:
    			  			
    			currentPage=1;
    			friends = true;
    			updateResources();
    			break;
    			
    		case MENU_MAP:
    			Intent intent = new Intent(this, ResourcesMap.class);
				DataManager.getInstance().putData(DataManager.RESOURCES_LIST,
						mList);
				startActivity(intent);
    			break;
    	}
    	
    	return super.onOptionsItemSelected(item);
    }
	
    protected void onListItemClick(ListView l, View v, int position, long id) {
    
    	userDialog = (User) mList.get(position); 

    	
    	if (friends)
    	{
    		if ( userDialog.getLatitude()==-1.0 && 
    			 userDialog.getLongitude()==-1.0)
 
    		{
    			showDialog(DIALOG_NO_LOCATION);
    			return;
    		}
    		
        	Intent i = new Intent(this, UserCard.class);
        	
	        i.putExtra("node",userDialog);
        	//i.putExtra("userId", userDialog.getId() );
        	//i.putExtra("distance", getDistance(userDialog.getLatitude(), userDialog.getLongitude(),userDialog.getLocation()).toString());
        	startActivity(i);
        	
    	}
    	else
    	{
    		if (mFriendsList != null){
    			int num_friends = mFriendsList.size();
    			for(int i = 0; i<num_friends; i++)
    				if(((User)mFriendsList.get(i)).getUsername().equals(userDialog.getUsername()))
    					return;
    		}
    		showDialog(DIALOG_ADD_FRIEND);
    	}
    }
    
	protected void onActivityResult (int requestCode, int resultCode, Intent data) {	 
		
		switch (requestCode) { 
		
	    	case REQUEST_FRIENDSHIP_LIST:
	    		
	    		// Update the list
	    		mList = LibreGeoSocial.getInstance().getFriendsList(true,0.0,1);    		
	    		GeoNodePositionComparator comparator = new GeoNodePositionComparator();
	    		Collections.sort(mList, comparator);
	        	mAdapter.notifyDataSetChanged();
	        	
	    		break;
		}
		
	}
    
    private void launchFriendShipList()
    {
    	Intent i = new Intent(this,FriendshipList.class);
    	startActivityForResult(i,REQUEST_FRIENDSHIP_LIST);    	
    }
    
    
    @Override
    protected Dialog onCreateDialog(int id) {
        
    	switch (id) {
        	case DIALOG_ADD_FRIEND:

		    	return new AlertDialog.Builder(this)
		        .setIcon(R.drawable.user_add_48)
		        .setCancelable(false)
		        .setTitle("Add Friend Petition")
		        .setMessage("Do you want to add '" + this.userDialog.getUsername() +"' as a friend?")
		        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
		            public void onClick(DialogInterface dialog, int whichButton) {
		
		                /* User clicked OK so do some stuff */
		            	if ( LibreGeoSocial.getInstance().setFriend(userDialog.getId() ) )
		            	{
		            		Toast.makeText(getBaseContext(), 
		     					   "Friend added correctly!", 
		     					   Toast.LENGTH_LONG).show();
		            	}
		            	else
		            	{
		            		Toast.makeText(getBaseContext(), 
			     					   "Error while the friend was added!", 
			     					   Toast.LENGTH_LONG).show();
		            	}
		            	removeDialog(DIALOG_ADD_FRIEND);
		            }
		        })
		        .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
		            public void onClick(DialogInterface dialog, int whichButton) {
		
		                /* User clicked Cancel so do some stuff */
		            	removeDialog(DIALOG_ADD_FRIEND);
		            }
		        })		        
		        .create();
		    	
        	case DIALOG_NO_FRIENDS:
        		
		        return new AlertDialog.Builder(this)	        
		        .setTitle("No friends!")
		        .setMessage("Currently, you haven't got friends. Press 'Menu' and go to 'Show all people' to view all the persons!")
		        .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
		            public void onClick(DialogInterface dialog, int whichButton) {
		            	//showDialog(DIALOG_COPIAGENDA);
		                /* User clicked OK so do some stuff */
		            }
		        })
		        .create();
		        
        	case DIALOG_FRIENDSHIP_INVITATIONS:
        		
		    	return new AlertDialog.Builder(this)
		        .setIcon(R.drawable.logo)
		        .setTitle("Friendship invitations")
		        .setMessage("You have some invitations to get friends. Do you want to see them now?")
		        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
		            public void onClick(DialogInterface dialog, int whichButton) {
		
		            	launchFriendShipList();
		            }
		        })
		        .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
		            public void onClick(DialogInterface dialog, int whichButton) {
		
		                /* User clicked Cancel so do some stuff */
		            }
		        })
		        .create();
        		

        	case DIALOG_NO_LOCATION:
        		
		        return new AlertDialog.Builder(this)	        
		        .setTitle("Don't Permission")
		        .setMessage("You haven't permission to see the location of your friend!")
		        .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
		            public void onClick(DialogInterface dialog, int whichButton) {
		            	//showDialog(DIALOG_COPIAGENDA);
		                /* User clicked OK so do some stuff */
		            }
		        })
		        .create();
        		
		    
        	case DIALOG_REMOVE_FRIEND:
        		
		    	return new AlertDialog.Builder(this)
		        .setIcon(R.drawable.user_delete_48)
		        .setTitle("Remove Friend Petition")
		        .setMessage("Do you want to remove '" + this.userDialog.getUsername() +"' as a friend?")
		        .setCancelable(false)
		        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
		            public void onClick(DialogInterface dialog, int whichButton) {
		
		                /* User clicked OK so do some stuff */
		            	if ( LibreGeoSocial.getInstance().deleteFriend(userDialog.getId() ) )
		            	{
		            		updateResources();
		            		
		            		Toast.makeText(getBaseContext(), 
		     					   "Friend deleted correctly!", 
		     					   Toast.LENGTH_LONG).show();
		            		
		            		
		            	}
		            	else
		            	{
		            		Toast.makeText(getBaseContext(), 
			     					   "Error while the friend was deleted!", 
			     					   Toast.LENGTH_LONG).show();
		            	}

		            	removeDialog(DIALOG_REMOVE_FRIEND);
		            }
		        })
		        .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
		            public void onClick(DialogInterface dialog, int whichButton) {
		
		                /* User clicked Cancel so do some stuff */
		            	removeDialog(DIALOG_REMOVE_FRIEND);
		            }
		        })
		        .create();
		    
    	}
    	return super.onCreateDialog(id);
    
	}
   
    private static String getDistance(Double longitude, Double latitude, Location location){
    	String distString = null;
        
		if ( latitude==-1.0 && 
			 longitude==-1.0)
		{
			distString = "Unknow Location";
		}
		else
		{
			
			// Calculate distance
			float dist = LocationUtils.calculateDistance (LocationService.getCurrentLocation(), 
														  location);
			
			distString = LocationUtils.displayDistance(dist, LocationUtils.AUTO);
		}
		return distString;
    }
    
	public static class FriendsAdapter extends BaseAdapter {

		private Context mContext;
		
		public FriendsAdapter (Context c) {
            mContext = c;
        }

		public int getCount() {
			// TODO Auto-generated method stub
			return mList.size();
		}

		public Object getItem(int position) {
			// TODO Auto-generated method stub
			return position;
		}

		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			View view;
			
	        if (convertView == null) {
	            // Make up a new view
	            LayoutInflater inflater = (LayoutInflater) mContext
	                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	            view = inflater.inflate(R.layout.generic_list, null);
	        } else {
	            // Use convertView if it is available
	            view = convertView;
	        }
			
	        
	        User user = (User) mList.get(position);	       	       
	        
	        ImageView img = (ImageView) view.findViewById(R.id.image);	 
	        
	        if (user.getAvatarId() == null)
	           	img.setImageResource(R.drawable.user_48);
	        else
	        	img.setImageBitmap (user.getAvatarBitmap());
	        	
			TextView t = (TextView) view.findViewById(R.id.title);
			t.setText( user.getName() + " (" + user.getUsername() +")");
			
			t = (TextView) view.findViewById(R.id.owner);
			
			String distString;

			distString = getDistance(user.getLatitude(), user.getLongitude(),user.getLocation());

			t.setText("State: " + user.getState() + "\n" + distString);
	        
			return view;
	        
		}

	}

	
}
